package com.jk.controller.util;

import com.jk.pojo.AnnotationLYG;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * poi导出工具类
 */
public class ExcelToolLYG implements Runnable{
    //当前线程需要导出的sheet页
    private XSSFSheet sheet;
    //当前sheet页需要导出的数据
    private List dataList;
    private Class clazz;
    //线程栅栏
    private CountDownLatch doneSignal;
    public ExcelToolLYG(XSSFSheet sheet, List dataList, Class clazz, CountDownLatch doneSignal){
        this.sheet = sheet;
        this.dataList =dataList;
        this.clazz = clazz;
        this.doneSignal = doneSignal;
    }
    public void run() {
        //设置表头
        Field[] porpertitys = clazz.getDeclaredFields();
        //创建第一行用来设置表头
        XSSFRow headRow = sheet.createRow(0);
        //创建一个需要导出字段的属性集合
        List<Field> exportFields = new ArrayList<Field>();
        //定义需要导出字段的下标计数器
        int count = 0;
        for (int i = 0; i < porpertitys.length; i++) {
            //根据注解类型获取当前属性上的对应注解实例 获取当前属性中是否含有导出注解 若有导出注解则导出该字段
            AnnotationLYG annotationLYG = porpertitys[i].getAnnotation(AnnotationLYG.class);
            //若该注解实例为空 则证明当前属性无此注解 不需要导出
            if(annotationLYG!=null){
                //count++ 先使用后赋值   ++count 先加1再赋值 exportField.exportName() 获取注解中的name值
                headRow.createCell(count++).setCellValue(annotationLYG.name());
                //当前字段需要导出则放入导出集合中
                exportFields.add(porpertitys[i]);
            }
        }
        //在excel中添加数据
        for (int rowIndex = 1; rowIndex <= dataList.size(); rowIndex++) {
            //循环创建数据行 createRow创建行线程不安全 需要加同步锁处理
            XSSFRow dataRow = getRowByIndex(rowIndex);
            //为数据行单元格设置内容
            for (int cellIndex = 0; cellIndex < exportFields.size(); cellIndex++) {
                //从list集合中获取当前集合对应的对象
                Object t = dataList.get(rowIndex-1);
                //设置当前类的私有属性为可访问状态
                exportFields.get(cellIndex).setAccessible(true);
                //获取类中属性值
                Object object;
                try {
                    //exportFields 需要导出的属性  t需要导出数据的数据对象  根据属性对象 从对应数据对象中获取属性的值
                    object = exportFields.get(cellIndex).get(t);
                    if(object!=null){
                        //instanceof 判断当前对象是否属于某个类型 若属于则返回true
                        if(object instanceof String){
                            dataRow.createCell(cellIndex).setCellValue(object.toString());
                        }else if(object instanceof Boolean){
                            dataRow.createCell(cellIndex).setCellValue((Boolean)object);
                        }else if(object instanceof Date){
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                            dataRow.createCell(cellIndex).setCellValue(sdf.format(object));
                        }
                    }else {
                        dataRow.createCell(cellIndex).setCellValue("");
                    }
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

            }
        }
        //当有一个线程运行结束之后 线程计数器中的数量-1 当线程计数器为0时 则证明所有线程结束运行
        doneSignal.countDown();
    }
    //为获取行操作添加同步锁机制
    public synchronized XSSFRow getRowByIndex(int rowIndex){
        return sheet.createRow(rowIndex);
    }
}
